	package com.foreveross.chameleon;
	
	import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
	
	import android.content.Context;
import android.widget.Toast;
	
	import com.foreveross.chameleon.config.ChameleonConfig;
import com.foreveross.chameleon.config.ChameleonConstants;
import com.foreveross.chameleon.manager.ModuleOperationService;
import com.foreveross.chameleon.model.ApplicationInfo;
import com.foreveross.chameleon.model.ModuleInfo;
import com.foreveross.chameleon.utils.FileCopeTool;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
	
	/**
	 * @descrption chameleon module mananger
	 * @author zhouzhineng
	 * 
	 */
	public class ModuleManager {
	
		protected static ModuleManager mInstance;
		protected Context mContext;
		protected Map<String, ModuleInfo> mModules;
		protected Map<String,ModuleInfo> mInstallModules;
		protected Map<String,ModuleInfo> mUpgradeModules;
		protected Map<String,ModuleInfo> mUnInstallModules;
		protected ModuleOperationService mModuleOperationService;
		protected class ConfigHeaderInfo {
	
		}
	
		private ModuleManager(Context context) {
			mContext = context;
			mModules = new HashMap<String,ModuleInfo>();
			mInstallModules = new HashMap<String,ModuleInfo>();
			mUpgradeModules = new HashMap<String,ModuleInfo>();
			mUnInstallModules = new HashMap<String,ModuleInfo>();
			//loadLocalModules();
		}
	
		public static ModuleManager getInstance(Context context) {
			if (mInstance == null) {
				mInstance = new ModuleManager(context);
				
			}
			return mInstance;
		}
		
		public void clear() {
			mModules.clear();
			mInstallModules.clear();
			mUpgradeModules.clear();
			mUnInstallModules.clear();
		}
	
		public void add2InstallList(ModuleInfo module) {
			mInstallModules.put(module.getIdentifier(),module);
		}
	
		public void add2UpgradeList(ModuleInfo module) {
			mUpgradeModules.put(module.getIdentifier(),module);
		}
	
		public void add2UnInstallList(ModuleInfo module) {
			mUnInstallModules.put(module.getIdentifier(), module);
		}
		
		public int getInstallCount() {
			return mInstallModules.size();
		}
		
		public int getUpgradeCount() {
			return mUpgradeModules.size();
		}
		
		public int getUnInstallCount() {
			return mUnInstallModules.size();
		}
		
		public void loadLocalModules() {
			String name = ChameleonConstants.APPINFO_CONFIG_FILE + ".json";
	        String results = new FileCopeTool(mContext).readerFile(ChameleonConfig.APP_PATH, name);
			GsonBuilder builder = new GsonBuilder();
		    Gson gson = builder.create();
		    ApplicationInfo localInfo = gson.fromJson(results, ApplicationInfo.class);
			Set<ModuleInfo> moduleSet = localInfo.getModules();
			if (moduleSet != null && moduleSet.size() > 0) {
				for (ModuleInfo module : moduleSet) {
					//modules.put(module.getIdentifier(), module);
					mModules.put(module.getIdentifier(), module);
				}
			}
	
			//return modules;
		}
	
		public Map<String, ModuleInfo> getModules() {
			return mModules;
		}
	
		public Map<String,ModuleInfo> getDownloadModules() {
			return mInstallModules;
		}
	
		public Map<String,ModuleInfo> getUpgradeModules() {
			return mUpgradeModules;
		}
	
		public List<ModuleInfo> getInstallList() {
			List<ModuleInfo> installList = new ArrayList<ModuleInfo>();
			Set<String> keySet = mInstallModules.keySet();
			ModuleInfo moduleInfo = null;
			for(String key : keySet) {
				moduleInfo = mInstallModules.get(key);
				installList.add(moduleInfo);
			}
			return installList;
		}
		
		public List<ModuleInfo> getUnInstallList() {
			List<ModuleInfo> uninstallList = new ArrayList<ModuleInfo>();
			Set<String> keyset = mUnInstallModules.keySet();
			ModuleInfo moduleInfo = null;
			for(String key : keyset) {
				moduleInfo = mUnInstallModules.get(key);
				uninstallList.add(moduleInfo);
			}
			return uninstallList;
		}
		
		public List<ModuleInfo> getUpgradeList() {
			List<ModuleInfo> upgradeList = new ArrayList<ModuleInfo>();
			Set<String> keySet = mUpgradeModules.keySet();
			ModuleInfo moduleInfo = null;
			for(String key : keySet) {
				moduleInfo = mUpgradeModules.get(key);
				upgradeList.add(moduleInfo);
			}
			return upgradeList;
		}
		
		public void compareAndSet(ApplicationInfo remoteApp) {
			mInstallModules.clear();
			mUpgradeModules.clear();
			mUnInstallModules.clear();
			Map<String,ModuleInfo> localModules = mModules;
			Set<ModuleInfo> remoteModules = remoteApp.getModules(); 
			ModuleInfo localModule = null;
			for(ModuleInfo remoteModule : remoteModules) {
				if(localModules != null) {
					if(localModules.containsKey(remoteModule.getIdentifier())) {
						localModule = localModules.get(remoteModule.getIdentifier());
						if(localModule.getBuild() < remoteModule.getBuild()) {
							mUpgradeModules.put(remoteModule.getIdentifier(), remoteModule);
						}
					} else {
						mUnInstallModules.put(remoteModule.getIdentifier(),remoteModule);
					}
				} else {
					mUnInstallModules.put(remoteModule.getIdentifier(), remoteModule);
				}
			}
			
		}
		
		
		public ModuleInfo getModule(String identify) {
			ModuleInfo module = null;
			if (mModules != null) {
				module = mModules.get(identify);
			}
			return module;
		}
	
		public void addModule(ModuleInfo module) {
			if (mModules != null && !mModules.containsKey(module.getIdentifier())) {
				mModules.put(module.getIdentifier(), module);
			}
			refreshModuleInfoConfigFile();
		}
	
		public void removeModule(String identify) {
			if (mModules != null && mModules.containsKey(identify)) {
				mModules.remove(identify);
			}
			refreshModuleInfoConfigFile();
		}
	
		public void updateModule(String identify, ModuleInfo module) {
			if (mModules != null && mModules.containsKey(identify)) {
				mModules.remove(identify);
				mModules.put(identify, module);
			}
			refreshModuleInfoConfigFile();
		}
	
		private void refreshModuleInfoConfigFile() {
	
		}
	
		public int getModuleCount() {
			int count = 0;
			if (mModules != null) {
				count = mModules.size();
			}
			return count;
		}
	
		public void autoDownload(List<ModuleInfo> downloadModules) {
	
			getModuleOperationService().autoDownload(downloadModules);
		}
	
		public void autoUpgrade(List<ModuleInfo> upgradeModules) {
			
			getModuleOperationService().autoUpgrade(upgradeModules);
		}
		
		public void uninstall(List<ModuleInfo> uninstallModules) {
			getModuleOperationService().batchUninstall(uninstallModules);
		}
		
		public void setModuleOperationService(ModuleOperationService moduleOperationService) {
			mModuleOperationService = moduleOperationService;
		}
		
		private ModuleOperationService getModuleOperationService() {
			return mModuleOperationService;
		}
		
		/**
		 * 第一次安装同步本地安装的模块信息到记录文件
		 */
		public void syncLocalModuleInfo() {
			String results = new FileCopeTool(mContext).getFromAssets("local_modules.json");
			try {
				JSONObject jsonObj = new JSONObject(results);
				if(jsonObj == null) {return;}
				if(jsonObj.has("list")) {
					JSONArray array = jsonObj.getJSONArray("list");
					JSONObject item = null;
					ModuleInfo module = null;
					Set<ModuleInfo> moduleSet = new HashSet<ModuleInfo>();
					for(int i = 0; i < array.length(); i++) {
						module = new ModuleInfo();
						item = array.getJSONObject(i);
						if(item.has("releaseNote")) {
							module.setReleaseNote(item.getString("releaseNote"));
						}
						module.setBuild(item.getInt("build"));
						module.setIdentifier(item.getString("identifier"));
						module.setDownloadUrl(item.getString("moduleUrl"));
						module.setVersion(item.getString("version"));
						module.setName(item.getString("name"));
						module.setModuleType(ModuleInfo.INSTALLED);
						moduleSet.add(module);
					}
					
					 ApplicationInfo localAppInfo = ApplicationInfo.getInstance(mContext);
				     localAppInfo.setMainModuleTag(jsonObj.getString("mainModuleTag"));
				     localAppInfo.setModules(moduleSet);
				     localAppInfo.save(localAppInfo);
				}
			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
}
